/**
 * Copyright (c) 2015-2017, Henry Yang 杨勇 (gismail@foxmail.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.lambkit.module.common.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.util.StrUtil;
import com.lambkit.core.Attr;
import com.lambkit.core.Lambkit;
import com.lambkit.core.LambkitResult;
import com.lambkit.db.*;
import com.lambkit.db.enjoy.EnjoySQL;
import com.lambkit.db.sql.Example;
import com.lambkit.module.common.CommonConfig;
import com.lambkit.module.common.row.SqlTemplate;
import com.lambkit.module.common.sql.SqlTemplateSQL;

import java.util.List;
import java.util.Map;

/**
 * @author yangyong 
 * @website: www.lambkit.com
 * @email: gismail@foxmail.com
 * @date ${date}
 * @version 1.0
 * @since 1.0
 */

public class SqlTemplateService extends AbstractDaoService<SqlTemplate> {
	private EnjoySQL enjoySQL = new EnjoySQL("sqltemplateEngine");
	public static SqlTemplateService of() {
		return Lambkit.get(SqlTemplateService.class);
	}
	public IRowDao<SqlTemplate> dao() {
		String dbPoolName = Lambkit.config(CommonConfig.class).getDbPoolName();
		return DbPool.use(dbPoolName).dao(SqlTemplate.class);
	}

	public IRowDao<SqlTemplate> dao(String dbPoolName) {
		return DbPool.use(dbPoolName).dao(SqlTemplate.class);
	}

	public SqlTemplate getTemplate(String key) {
		if(StrUtil.isBlank(key)) {
			return null;
		}
		if(key.indexOf(".") > 0) {
			String name =  key.substring(0, key.lastIndexOf("."));
			String catalog = key.substring(key.lastIndexOf(".")+1);
			Example example = SqlTemplateSQL.of().andNameEqualTo(name).andCatalogEqualTo(catalog).example();
			example.setCount(1);
			return dao().findFirst(example);
		} else {
			Example example = SqlTemplateSQL.of().andNameEqualTo(key).example();
			example.setCount(1);
			return dao().findFirst(example);
		}
	}


	public List<Sql> getSql(SqlTemplate sqlTemplate, Map<String, Object> data) {
		String content = sqlTemplate.getContent();
		List<Sql> sqlList = CollUtil.newArrayList();
		if(StrUtil.isBlank(content)) {
			return sqlList;
		}
		String[] sqlContents = content.split(";");
		for (String sqlContent : sqlContents) {
			Sql sql = enjoySQL.getSqlPara(sqlContent.trim(), data);
			sqlList.add(sql);
		}
		return sqlList;
	}

	public List<Sql> getSql(SqlTemplate sqlTemplate, Object... data) {
		String content = sqlTemplate.getContent();
		List<Sql> sqlList = CollUtil.newArrayList();
		if(StrUtil.isBlank(content)) {
			return sqlList;
		}
		String[] sqlContents = content.split(";");
		for (String sqlContent : sqlContents) {
			Sql sql =enjoySQL.getSqlPara(sqlContent.trim(), data);
			sqlList.add(sql);
		}
		return sqlList;
	}

	//////////////////////////////////////////////////////////////////
	///
	public LambkitResult executeQuerys(List<Sql> sqls, String dbname, Integer page_number, Integer page_size) {
		List<Object> queryResult = CollUtil.newArrayList();
		TimeInterval timer0 = DateUtil.timer();
		for (Sql sql : sqls) {
			String sqlStr = sql.getSql().trim();
			TimeInterval timer = DateUtil.timer();
			if(sqlStr.toLowerCase().startsWith("select "))  {
				PageData<RowData> sqlData = paginate(sql, dbname, page_number, page_size);
				long interval = timer.interval();//花费毫秒数
				queryResult.add(LambkitResult.success().data(sqlData).message("paginate")
						.attr(Attr.by("execute_time", interval).set("finish_time", DateUtil.now())));
			} else {
				int count = execute(sql, dbname);
				long interval = timer.interval();//花费毫秒数
				queryResult.add(LambkitResult.success().data(count).message("execute")
						.attr(Attr.by("execute_time", interval).set("finish_time", DateUtil.now())));
			}
		}
		long interval0 = timer0.interval();//花费毫秒数
		return LambkitResult.success().data(queryResult)
				.attr(Attr.by("total_time", interval0).set("finish_time", DateUtil.now()));
	}

	public LambkitResult executeQuery(Sql sql, String dbname, Integer page_number, Integer page_size) {
		String sqlStr = sql.getSql().trim();
		TimeInterval timer = DateUtil.timer();
		if(sqlStr.toLowerCase().startsWith("select "))  {
			PageData<RowData> sqlData = paginate(sql, dbname, page_number, page_size);
			long interval = timer.interval();//花费毫秒数
			return LambkitResult.success().data(sqlData).message("paginate")
					.attr(Attr.by("execute_time", interval).set("finish_time", DateUtil.now()));
		} else {
			int count = execute(sql, dbname);
			long interval = timer.interval();//花费毫秒数
			return LambkitResult.success().data(count).message("execute")
					.attr(Attr.by("time", interval).set("finish_time", DateUtil.now()));
		}
	}

	//////////////////////////////////////////////////////////////////
	/// Queries	4
	/// Updated Rows	0
	/// Execute time (ms)	234
	/// Fetch time (ms)	0
	/// Total time (ms)	234
	/// Finish time	Sat Nov 15 09:30:50 CST 2025
	//////////////////////////////////////////////////////////////////
	///



	public int execute(Sql sql, String dbname) {
		if(sql==null) {
			return 0;
		}
		return DbPool.use(dbname).update(sql);
	}

	public List<RowData> find(Sql sql, String dbname, Integer count) {
		if(sql==null) {
			return null;
		}
		if(count==null || count==0) {
			count = 1000;
		}
		PageData<RowData> data = paginate(sql, dbname, 1, count);
		return data.getList();
	}

	public RowData findFirst(Sql sql, String dbname) {
		if(sql==null) {
			return null;
		}
		return DbPool.use(dbname).findFirst(sql);
	}

	public PageData<RowData> paginate(Sql sql, String dbname, Integer page_number, Integer page_size) {
		if(sql==null) {
			return null;
		}
		return DbPool.use(dbname).paginate(page_number, page_size, sql);
	}

//	public List<RowData> find(SqlTemplate sqlTemplate, String db_pool_name, Map<String, Object> data) {
//		if(sqlTemplate==null) {
//			return null;
//		}
//		String dbname = StrUtil.isBlank(db_pool_name) ? sqlTemplate.getDbname() : db_pool_name;
//		dbname = StrUtil.isBlank(dbname) ? DbPool.DEFAULT_NAME : dbname;
//		return DbPool.use(dbname).find(getSql(sqlTemplate, data));
//	}
//
//	public List<RowData> find(SqlTemplate sqlTemplate, String db_pool_name, Object... data) {
//		if(sqlTemplate==null) {
//			return null;
//		}
//		String dbname = StrUtil.isBlank(db_pool_name) ? sqlTemplate.getDbname() : db_pool_name;
//		dbname = StrUtil.isBlank(dbname) ? DbPool.DEFAULT_NAME : dbname;
//		return DbPool.use(dbname).find(getSql(sqlTemplate, data));
//	}

	//////////////////////////////////////////////////////////////////

//	public List<RowData> find(String tamplate_name, String db_pool_name, Map<String, Object> data) {
//		return find(getTemplate(tamplate_name), db_pool_name, data);
//	}
//
//	public List<RowData> find(String tamplate_name, String db_pool_name, Object... data) {
//		return find(getTemplate(tamplate_name), db_pool_name, data);
//	}
//
//	public RowData findFirst(String tamplate_name, String db_pool_name, Map<String, Object> data) {
//		return findFirst(getTemplate(tamplate_name), db_pool_name, data);
//	}
//
//	public RowData findFirst(String tamplate_name, String db_pool_name, Object... data) {
//		return findFirst(getTemplate(tamplate_name), db_pool_name, data);
//	}
//
//	public PageData<RowData> paginate(String tamplate_name, String db_pool_name, Integer page_number, Integer page_size, Map<String, Object> data) {
//		return paginate(getTemplate(tamplate_name), db_pool_name, page_number, page_size, data);
//	}
//
//	public PageData<RowData> paginate(String tamplate_name, String db_pool_name, Integer page_number, Integer page_size, Object... data) {
//		return paginate(getTemplate(tamplate_name), db_pool_name, page_number, page_size, data);
//	}
//
//	//////////////////////////////////////////////////////////////////
//
//	public <T extends RowModel<T>> List<T> find(String tamplate_name, String db_pool_name, Class<T> clazz, Map<String, Object> data) {
//		SqlTemplate sqlTemplate = getTemplate(tamplate_name);
//		if(sqlTemplate==null) {
//			return null;
//		}
//		String dbname = StrUtil.isBlank(db_pool_name) ? sqlTemplate.getDbname() : db_pool_name;
//		dbname = StrUtil.isBlank(dbname) ? DbPool.DEFAULT_NAME : dbname;
//		return DbPool.use(dbname).dao(clazz).find(getSql(sqlTemplate, data));
//	}
//
//	public <T extends RowModel<T>> List<T> find(String tamplate_name, String db_pool_name, Class<T> clazz, Object... data) {
//		SqlTemplate sqlTemplate = getTemplate(tamplate_name);
//		if(sqlTemplate==null) {
//			return null;
//		}
//		String dbname = StrUtil.isBlank(db_pool_name) ? sqlTemplate.getDbname() : db_pool_name;
//		dbname = StrUtil.isBlank(dbname) ? DbPool.DEFAULT_NAME : dbname;
//		return DbPool.use(dbname).dao(clazz).find(getSql(sqlTemplate, data));
//	}
//
//	public <T extends RowModel<T>> T findFirst(String tamplate_name, String db_pool_name, Class<T> clazz, Map<String, Object> data) {
//		SqlTemplate sqlTemplate = getTemplate(tamplate_name);
//		if(sqlTemplate==null) {
//			return null;
//		}
//		String dbname = StrUtil.isBlank(db_pool_name) ? sqlTemplate.getDbname() : db_pool_name;
//		dbname = StrUtil.isBlank(dbname) ? DbPool.DEFAULT_NAME : dbname;
//		return (T) DbPool.use(dbname).dao(clazz).findFirst(getSql(sqlTemplate, data));
//	}
//
//	public <T extends RowModel<T>> T findFirst(String tamplate_name, String db_pool_name, Class<T> clazz, Object... data) {
//		SqlTemplate sqlTemplate = getTemplate(tamplate_name);
//		if(sqlTemplate==null) {
//			return null;
//		}
//		String dbname = StrUtil.isBlank(db_pool_name) ? sqlTemplate.getDbname() : db_pool_name;
//		dbname = StrUtil.isBlank(dbname) ? DbPool.DEFAULT_NAME : dbname;
//		return (T) DbPool.use(dbname).dao(clazz).findFirst(getSql(sqlTemplate, data));
//	}
//
//	public <T extends RowModel<T>> PageData<T> paginate(String tamplate_name, String db_pool_name, Class<T> clazz, Integer page_number, Integer page_size, Map<String, Object> data) {
//		SqlTemplate sqlTemplate = getTemplate(tamplate_name);
//		if(sqlTemplate==null) {
//			return null;
//		}
//		String dbname = StrUtil.isBlank(db_pool_name) ? sqlTemplate.getDbname() : db_pool_name;
//		dbname = StrUtil.isBlank(dbname) ? DbPool.DEFAULT_NAME : dbname;
//		return DbPool.use(dbname).dao(clazz).paginate(page_number, page_size, getSql(sqlTemplate, data));
//	}
//
//	public <T extends RowModel<T>> PageData<T> paginate(String tamplate_name, String db_pool_name, Class<T> clazz, Integer page_number, Integer page_size, Object... data) {
//		SqlTemplate sqlTemplate = getTemplate(tamplate_name);
//		if(sqlTemplate==null) {
//			return null;
//		}
//		String dbname = StrUtil.isBlank(db_pool_name) ? sqlTemplate.getDbname() : db_pool_name;
//		dbname = StrUtil.isBlank(dbname) ? DbPool.DEFAULT_NAME : dbname;
//		return DbPool.use(dbname).dao(clazz).paginate(page_number, page_size, getSql(sqlTemplate, data));
//	}
}
